package com.xindacloud.sms.adapter.service.notify.impl;

import com.google.gson.Gson;
import com.xindacloud.sms.adapter.bo.SubmitMessageBO;
import com.xindacloud.sms.adapter.dto.SqsSubmitMessageParamDTO;
import com.xindacloud.sms.adapter.entity.*;
import com.xindacloud.sms.adapter.exception.ServiceException;
import com.xindacloud.sms.adapter.service.business.*;
import com.xindacloud.sms.adapter.service.notify.INotifyService;
import com.xindacloud.sms.adapter.service.sms.ISubmitMessageService;
import com.xindacloud.sms.adapter.utils.Base64DecodeHelp;
import com.xindacloud.sms.adapter.utils.MessageTypeHelp;
import com.xindacloud.sms.adapter.utils.StatusEum;
import com.xindacloud.sms.adapter.utils.UnionResultHelp;
import com.xindacloud.sms.adapter.vo.SubmitMessageResultVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service("submitSmsNotifyService")
@Slf4j
public class SubmitSmsNotifyServiceImpl implements INotifyService {


    private final ISmsAgentService smsAgentService;

    private final ISmsAgentGroupService smsAgentGroupService;

    private final ISmsUserAllowOperatorService smsUserAllowOperatorService;

    private final ISmsAgentRouteService smsRouteService;

    private final ISmsSubmissionRecordService smsSubmissionRecordService;

    private final ISmsUserService smsUserService;

    private final Map<String, ISubmitMessageService> submitMessageServiceStrategyMap = new ConcurrentHashMap<>();

    @Autowired
    public SubmitSmsNotifyServiceImpl(Map<String, ISubmitMessageService> submitMessageServiceStrategyMap,
                                      ISmsAgentService smsAgentService,
                                      ISmsAgentGroupService smsAgentGroupService,
                                      ISmsUserAllowOperatorService smsUserAllowOperatorService,
                                      ISmsAgentRouteService smsRouteService,
                                      ISmsSubmissionRecordService smsSubmissionRecordService,
                                      ISmsUserService userService) {
        this.submitMessageServiceStrategyMap.clear();
        submitMessageServiceStrategyMap.forEach(this.submitMessageServiceStrategyMap::put);
        this.smsAgentService = smsAgentService;
        this.smsAgentGroupService = smsAgentGroupService;
        this.smsUserAllowOperatorService = smsUserAllowOperatorService;
        this.smsRouteService = smsRouteService;
        this.smsSubmissionRecordService = smsSubmissionRecordService;
        this.smsUserService = userService;
    }

    private SubmitMessageResultVO submitMessage(SubmitMessageBO submitMessageBO) {

        final String recipient = submitMessageBO.getRecipient();
        final Integer userId = submitMessageBO.getUserId();
        final String encoding = submitMessageBO.getEncoding();
        final String messageBody = submitMessageBO.getMessageBody();
        final String taskId = submitMessageBO.getTaskId();
        final String senderId = submitMessageBO.getSenderId();
        final Integer messageCount = submitMessageBO.getMessageCount() == 0 ? 1 : submitMessageBO.getMessageCount();
        Optional.ofNullable(recipient)
                .filter(StringUtils::isNotEmpty)
                .orElseThrow(() -> new ServiceException("目标号码不能为空", UnionResultHelp.StatusEnum.ParamsFail.code()));
        try {
            //获取最优惠或者指定的运营商对应的平台发送
            final SmsUserAllowOperator allowOperator = this.chooseAssignationOperators(userId);
            //获取通道代理商的api_key,apiSecret
            final SmsAgent agent = smsAgentService.queryAgentById(allowOperator.getAgentId());
            //获取通道代理商组名
            final SmsAgentGroup smsAgentGroup = smsAgentGroupService.queryOneAgentInfoById(agent.getGroupId());
            final SmsAgentRoute smsAgentRoute = smsRouteService.querySmsRouteById(smsAgentGroup.getRouteId());
            log.info("###获取到的路由ID:{},路由服务：{}", smsAgentRoute.getRouteId(), smsAgentRoute.getRouteServiceBeanId());
            //根据通道代理商组名路由到不同的服务发送短信
            final BigDecimal maxPrice = fetchMaxPricing(userId).getPrice();
            final String agentId = agent.getAgentId();
            final String networkCode = allowOperator.getNetworkCode();
            SubmitMessageBO messageBO = SubmitMessageBO.builder()
                    .agentId(agentId)
                    .apiKey(Base64DecodeHelp.decode(agent.getApiKey()))
                    .apiSecret(Base64DecodeHelp.decode(agent.getApiSecret()))
                    .apiUrl(agent.getApiUrl())
                    .senderId(senderId)
                    .callBackUrl(agent.getCallBackUrl())
                    .price(maxPrice)
                    .netWork(networkCode)
                    .encoding(encoding)
                    .messageBody(messageBody)
                    .messageCount(messageCount)
                    .userId(userId)
                    .taskId(taskId)
                    .recipient(recipient)
                    .build();

            final SubmitMessageResultVO resultVO = (SubmitMessageResultVO) submitMessageServiceStrategyMap
                    .get(smsAgentRoute.getRouteServiceBeanId())
                    .submitMessage(messageBO);
            final BigDecimal calcMessagePrice = MessageTypeHelp.calcMessagePrice(maxPrice, messageCount);
            final SmsSubmissionRecord submissionRecord = SmsSubmissionRecord.builder()
                    .agentId(agentId)
                    .free(calcMessagePrice)
                    .messageId(resultVO.getMessageId())
                    .network(StringUtils.isNotEmpty(resultVO.getNetwork()) ? resultVO.getNetwork() : networkCode)
                    .sendFrom(senderId)
                    .submitStatusCode(resultVO.getSubmitStatus())
                    .sendTo(recipient)
                    .taskId(taskId)
                    .userId(userId)
                    .build();
            smsSubmissionRecordService.updateSmsSubmissionRecordFor(submissionRecord);
            //更新用户账户
            smsUserService.updateSmsPrice(userId, calcMessagePrice);
            return resultVO;

        } catch (ServiceException e) {
            final SmsSubmissionRecord record = SmsSubmissionRecord.builder()
                    .sendFrom(senderId)
                    .submitStatusCode(e.getErrorCode())
                    .errorText(e.getMessage())
                    .finalStatus(StatusEum.FAILED.desc)
                    .sendTo(recipient)
                    .taskId(taskId)
                    .userId(userId)
                    .build();
            smsSubmissionRecordService.updateSmsSubmissionRecordFor(record);
        }
        return null;
    }

    private SmsUserAllowOperator chooseAssignationOperators(Integer userId) {
        //获取可用的运营商
        final SmsUserAllowOperator smsUserAllowOperator = filterDisableAgent(userId)
                .stream()
                .filter(SmsUserAllowOperator::getStatus)
                .collect(Collectors.toList())
                .get(0);
        log.info("使用agentId:{},operator:{}指定的运营商发送,成本价为:", smsUserAllowOperator.getAgentId(),
                smsUserAllowOperator.getOperatorId(),
                smsUserAllowOperator.getCostPrice());
        return smsUserAllowOperator;
    }

    private SmsUserAllowOperator fetchMaxPricing(Integer userId) {
        //获取最高价格的运营商
        final List<SmsUserAllowOperator> maxPricingList = smsUserAllowOperatorService.queryMaxPriceOrderByDesc(userId);
        SmsUserAllowOperator maxUserAllowOperator = maxPricingList.get(0);
        log.info("使用agentId:{},operator:{},指定的运营商售价扣费,售价为:",
                maxUserAllowOperator.getAgentId(),
                maxUserAllowOperator.getOperatorId(),
                maxUserAllowOperator.getPrice());
        return maxUserAllowOperator;
    }


    @NotNull
    private List<SmsUserAllowOperator> filterDisableAgent(Integer userId) {
        //查询所有运营商价格最高列表按价格降序
        final List<SmsUserAllowOperator> minCostPricingList = smsUserAllowOperatorService.queryMinCostPriceOrderByAsc(userId);
        //smsUserAllowOperatorService.queryMaxPriceOrderByDesc(userId);
        //把禁用的代理账户过滤掉
        final List<SmsAgent> smsAgents = smsAgentService.queryAvailableAgentList(minCostPricingList.stream().map(SmsUserAllowOperator::getAgentId).collect(Collectors.toList()));
        final List<SmsUserAllowOperator> filterPriceList = new ArrayList<>();
        for (SmsUserAllowOperator allowOperator : minCostPricingList) {
            for (SmsAgent agent : smsAgents) {
                if (Objects.equals(allowOperator.getAgentId(), agent.getAgentId()) && agent.getStatus()) {
                    filterPriceList.add(allowOperator);
                }
            }
        }
        return filterPriceList;
    }


    @Override
    public void perform(String data) {
        SqsSubmitMessageParamDTO sqsSubmitMessageDTO = new Gson().fromJson(data, SqsSubmitMessageParamDTO.class);
        try {
            sqsSubmitMessageDTO.getRecipientList()
                    .stream()
                    .parallel()
                    .forEach(recipient -> this.submitMessage(SubmitMessageBO
                            .builder()
                            .encoding(sqsSubmitMessageDTO.getEncoding())
                            .messageBody(sqsSubmitMessageDTO.getMessageBody())
                            .messageCount(sqsSubmitMessageDTO.getMessageCount())
                            .userId(sqsSubmitMessageDTO.getUserId())
                            .taskId(sqsSubmitMessageDTO.getTaskId())
                            .senderId(sqsSubmitMessageDTO.getSender())
                            //.projectId(sqsSubmitMessageDTO.getProjectId())
                            .recipient(recipient)
                            .build()));
        } catch (Exception e) {
            log.error("处理发送短信异常:{}", e.getMessage(), e);
        }

    }
}
